// 没有package语句，则属于无名包
package chapter4.com.blover.corejava; // 以一个逆序因特网域名作为包名。源文件必须放在与包名匹配的子目录中
// 我这里的基目录是JAVA-SE11，上面路径不得不多了一个chapter4
// java chapter4/com/blover/corejava/Main.java
// 没有多个main方法的情况下，使用java chapter4.com.blover.corejava.Main运行class

// 不允许import java.*;
import java.util.*; // 导入整个包。类似C++的using namespace
import java.time.LocalDate; // 导入某个类

// 一个源文件中，只能有一个公共类，文件名必须与之匹配
public class Main {

    @SuppressWarnings("unused")
    static private Color maincolor = new Color("none"); // 聚合
    @SuppressWarnings("unused")
    static private void setColor(Color color) { // 依赖
        maincolor = color;
    }
    // 以及继承

    public static void main(String[] args) {
        // 对象本身是一个引用（类似C++里的对象指针）
        Date date; // 定义了一个对象变量，但是未引用任何变量。对其调方法会出错(NullPointerException)
        date = new Date();
        System.out.println(date.toString());
        date = null; // 可以显式地赋值为null
        LocalDate localdate = LocalDate.of(2024, 4, 25); // LocalDate没有实现构造器，而是要我们通过工厂方法来构造
        var localdate1 = localdate.plusDays(1); // LocalDate属于不可变对象，只存在访问器方法。这里会返回新对象
        System.out.println(localdate1.toString()); // 2024-04-26

        Color color1 = new Color("red");
        color1.setColorStr("blue");
        System.out.println(color1.getColorInfo());
    }
}

// OOP——对象的三个特性：状态、行为和标识

class Color {
    // 实例字段。这是**对象中的数据**
    private String color;
    private int id;
    private StringBuilder info;

    static int counter;

    // 所有字段一开始都是零值

    // 静态初始化块
    static {
        counter = 0;
    }
    // 初始化块
    {
        id = counter++;
    }

    // 构造器
    // 默认构造器Color()将被删除
    public Color(String acolor) { // Java中是按值传递
        // 所有字段一开始都是零值
        if(acolor == null) { // 对于对象变量，要清楚自己到底接不接受可有可无的值，然后做一下null检查
            System.out.println("null value!");
        }
        color = Objects.requireNonNullElse("" + acolor, ""); // 隐藏了this.color前的this
        // “严格型”
        // color = Objects.requireNonNull(acolor);
        info = new StringBuilder(); // final实例字段必须在构造对象时初始化
    }
    // 也可以根据不同的函数签名重载方法
    public Color(String acolor, String info_str) {
        this(acolor); // 在构造器的第一个语句中，可以用this(...)调另一个构造器
        info.append(info_str);
    }

    // 方法。这是**操作数据的方法**

    // **访问器方法**
    String getColorStr() { 
        // 注意，这里要返回color的克隆，不然调用者也能操作color
        return new String(color);
    }

    String getColorInfo() { 
        return info.toString();
    }

     // **更改器方法**
    void setColorStr(String acolor) {
        info.append(id + ": " + color + " -> " + acolor + "; "); // final修饰的是“对象指针”，至于指向的内容本身是可变的
        color = new String(acolor);
    }

    // 静态工厂方法
    static Color of(String acolor) {
        var obj = new Color(acolor);
        obj.id = counter++;
        return obj;
    }

    // Java有GC，不支持析构器

    // 每个类都可以有一个main方法，这常用于对类进行单元测试
    public static void main(String[] args) {
        System.out.println("Hello World");
        // getColorInfo(); // 错误。静态方法中不能使用动态方法
    }
    // 但注意这样就不能通过java Main来启动class文件了（仍然可以直接java Main.java）
    // 可以把Main和Color分到两个类里头
}